﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace CloudShot.Core.Utils
{
  /// <summary>
  /// Represents the utility class to resize <see cref="Image"/> by different ways.
  /// </summary>
  /// <remarks>http://www.codeproject.com/KB/GDI-plus/imageresize.aspx</remarks>
  public static class ImgResizer
  {
    /// <summary>
    /// Resizes <paramref name="image"/> to fixed size with base proportions saving.
    /// </summary>
    /// <param name="image">An image to resize.</param>
    /// <param name="width">A final width of the image.</param>
    /// <param name="height">A final height of the image.</param>
    /// <param name="fillColor">A color to fill empty parts of final image.</param>
    /// <param name="interpolationMode">An <see cref="InterpolationMode"/> for final image.</param>
    /// <returns>The resized image.</returns>
    public static Image FixedSize(Image image, int width, int height, Color fillColor,
                                  InterpolationMode interpolationMode = InterpolationMode.HighQualityBicubic)
    {
      return Resize(image, width, height, true, fillColor, interpolationMode);
    }

    /// <summary>
    /// Resizes <paramref name="image"/> with base proportions saving.
    /// </summary>
    /// <param name="image">An image to resize.</param>
    /// <param name="width">A final width of the image.</param>
    /// <param name="height">A final height of the image.</param>
    /// <param name="interpolationMode">An <see cref="InterpolationMode"/> for final image.</param>
    /// <returns>The resized image.</returns>
    public static Image Resize(Image image, int width, int height, InterpolationMode interpolationMode = InterpolationMode.HighQualityBicubic)
    {
      return Resize(image, width, height, false, Color.Transparent, interpolationMode);
    }

    /// <summary>
    /// Resizes image to specified size with base proportion saving and creates thumbnail from it using <see cref="Image.GetThumbnailImage"/> method.
    /// </summary>
    /// <param name="image">An image to resize.</param>
    /// <param name="width">A final width of the image.</param>
    /// <param name="height">A final height of the image.</param>
    /// <returns>The resized image.</returns>
    public static Image Thumbnail(Image image, int width, int height)
    {
      double k1 = ((double)width) / image.Width;
      double k2 = ((double)height) / image.Height;
      double k = (k1 > k2) ? k2 : k1;

      int w = (int)(image.Width * k);
      int h = (int)(image.Height * k);

      return image.GetThumbnailImage(w, h, () => false, IntPtr.Zero);
    }

    /// <summary>
    /// Resizes <paramref name="image"/> to specified size with base proportions saving.
    /// </summary>
    /// <param name="image">An image to resize.</param>
    /// <param name="width">A final width of the image.</param>
    /// <param name="height">A final height of the image.</param>
    /// <param name="fixSize">A <see cref="bool"/> paramener indicates that final image must be fixed size.</param>
    /// <param name="fillColor">A color to fill empty parts of final image.</param>
    /// <param name="interpolationMode">An <see cref="InterpolationMode"/> for final image.</param>
    /// <returns>The resized image.</returns>
    private static Image Resize(Image image, int width, int height, bool fixSize, Color fillColor,
                                InterpolationMode interpolationMode = InterpolationMode.HighQualityBicubic)
    {
      int sourceWidth = image.Width;
      int sourceHeight = image.Height;
      int destX = 0;
      int destY = 0;

      float nPercent = 0;
      float nPercentW = 0;
      float nPercentH = 0;

      nPercentW = (width / (float)sourceWidth);
      nPercentH = (height / (float)sourceHeight);
      nPercent = nPercentH < nPercentW ? nPercentH : nPercentW;

      if (fixSize)
      {
        if (nPercentH < nPercentW)
          destX = Convert.ToInt16((width - (sourceWidth * nPercent)) / 2);
        else
          destY = Convert.ToInt16((height - (sourceHeight * nPercent)) / 2);
      }

      int destWidth = (int)(sourceWidth * nPercent);
      int destHeight = (int)(sourceHeight * nPercent);

      int bmpWidth = fixSize ? width : destWidth;
      int bmpHeight = fixSize ? height : destHeight;
      var bmPhoto = new Bitmap(bmpWidth, bmpHeight, PixelFormat.Format32bppArgb);

      bmPhoto.SetResolution(image.HorizontalResolution, image.VerticalResolution);

      using (Graphics grPhoto = Graphics.FromImage(bmPhoto))
      {
        grPhoto.Clear(fillColor);
        grPhoto.InterpolationMode = interpolationMode;

        grPhoto.DrawImage(image, new Rectangle(destX, destY, destWidth, destHeight), new Rectangle(0, 0, sourceWidth, sourceHeight), GraphicsUnit.Pixel);

        grPhoto.Dispose();
      }

      return bmPhoto;
    }
  }
}